package com.hhck.controller;

import com.google.code.kaptcha.Producer;
import com.hhck.constants.Constants;
import com.hhck.entity.CurrentUser;
import com.hhck.entity.LoginUser;
import com.hhck.entity.Result;
import com.hhck.entity.User;
import com.hhck.service.UserService;
import com.hhck.utils.DigestUtil;
import com.hhck.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

@RestController
public class LoginController {

    // 注入DefaultKaptcha的Bean对象（验证码工具生成验证码图片）
    @Resource(name = "captchaProducer")
    private Producer producer;

    // 注入Redis模板
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private UserService userService;

    @Autowired
    private TokenUtils tokenUtils;

    /**
     * 生成验证码图片
     */
    @RequestMapping("/captcha/captchaImage")
    public void captchaImage(HttpServletResponse response) {

        // 生成验证码文本
        String text = producer.createText();
        // 使用验证码文本生成验证码图片，BufferedImage对象代表生成的验证码图片在内存中
        BufferedImage image = producer.createImage(text);

        // 将验证码文本作为key保存到Redis，并设置过期时间5分钟
        redisTemplate.opsForValue().set(text, "", 60 * 5, TimeUnit.SECONDS);

        // 设置响应头
        response.setContentType("image/jpeg");
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
            // 使用响应对象的字节输出流写入验证码图片，将验证码图片响应给前端
            ImageIO.write(image, "jpg", out);
            out.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    /**
     * 登录请求
     */
    @RequestMapping("/login")
    public Result login(@RequestBody LoginUser loginUser) {

        // 首先校验验证码（判断Redis中是否存在用户输入的验证码）
        if (!redisTemplate.hasKey(loginUser.getVerificationCode())) {
            // 不存在
            return Result.err(Result.CODE_ERR_BUSINESS, "验证码错误！");
        }

        // 根据账号查询用户
        User user = userService.queryUserByUserCode(loginUser.getUserCode());

        // 判断账号是否存在
        if (user == null) {
            // 不存在
            return Result.err(Result.CODE_ERR_BUSINESS, "账号不存在！");
        }

        // 判断用户是否审核
        if (user.getUserState().equals(Constants.USER_STATE_NOT_PASS)) {
            // 未审核
            return Result.err(Result.CODE_ERR_BUSINESS, "账号未审核！");
        }

        // 判断密码是否正确（获取用户输入的密码，MD5加密后与真实密码对比）
        if (!DigestUtil.hmacSign(loginUser.getUserPwd()).equals(user.getUserPwd())) {
            // 不正确
            return Result.err(Result.CODE_ERR_BUSINESS, "密码不正确！");
        }
        // 代码执行到这里说明用户输入的信息正确

        // 创建当前用户
        CurrentUser currentUser = new CurrentUser(user.getUserId(), user.getUserCode(), user.getUserName());
        // 生成JWToken
        String token = tokenUtils.loginSign(currentUser, user.getUserPwd());
        // 向客户端响应JWToken
        return Result.ok("登录成功", token);
    }

    /**
     * 获取当前登录用户信息
     */
    @GetMapping("/curr-user")
    public Result currentUser(@RequestHeader(Constants.HEADER_TOKEN_NAME) String token) {

        // 通过token解析获取当前用户
        CurrentUser currentUser = tokenUtils.getCurrentUser(token);
        if (currentUser != null) {
            // 当前用户不为空，响应给前端
            return Result.ok(currentUser);
        }
        return Result.err(Result.CODE_ERR_SYS, "获取当前用户信息失败！");
    }

    /**
     * 退出登录
     */
    @RequestMapping("/logout")
    public Result logout(@RequestHeader(Constants.HEADER_TOKEN_NAME) String token) {

        // 从Redis中删除token
        if (token != null) {
            redisTemplate.delete(token);
        }

        return Result.ok("退出成功！");
    }

}

